package com.example.gateway.middle.config;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;

/**
 * @author wangjinlong
 * @date 2022/2/16 17:32
 */
@Configuration
public class GatewayConfiguration {

    /**
     * 设置API管理
     * ApiDefinition：用户自定义的 API 定义分组，可以看做是一些 URL 匹配的组合。
     * 比如我们可以定义一个 API 叫 my_api，请求 path 模式为 /foo/** 和 /baz/** 的都归到 my_api 这个 API 分组下面。
     * 限流的时候可以针对这个自定义的 API 分组维度进行限流。
     */
    @PostConstruct
    private void initCustomizedApis() {
        Set<ApiDefinition> definitions = new HashSet<>();

        ApiDefinition apiConsumer = new ApiDefinition(ResourceKey.KEY_CONSUMER)
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern(ResourceKey.KEY_CONSUMER_REGEX)
                            .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_REGEX));
                }});
        definitions.add(apiConsumer);

        ApiDefinition apiProvider = new ApiDefinition(ResourceKey.KEY_PROVIDER)
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem().setPattern(ResourceKey.KEY_PROVIDER_REGEX)
                            .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_REGEX));
                }});
        definitions.add(apiProvider);

        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

    /**
     * 配置限流规则
     */
    @PostConstruct
    private void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule(ResourceKey.KEY_PROVIDER)
                .setCount(1)
                .setIntervalSec(1));

        rules.add(new GatewayFlowRule(ResourceKey.KEY_CONSUMER)
                .setCount(1)
                .setIntervalSec(1)
        );
        GatewayRuleManager.loadRules(rules);

        // 网关限流降级回退
        GatewayCallbackManager.setBlockHandler(new MyBlockRequestHandler());
    }

}
